package edu.ccut.saturn.basecomponent.database.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.commons.jexl.ExpressionFactory;
import org.apache.commons.jexl.JexlHelper;

import edu.ccut.saturn.component.IParameterContext;
import edu.ccut.saturn.component.SaturnComponentException;

/**
 * @author Sagittarius
 *
 */
/**
 * @author Sagittarius
 *
 */
public class ConditionUtils {
	
	public final static String SEPARATE = "--";

	private final static String NEWLINE = "\n";

	private final static String LIKE = "LIKE";

	private final static String KEY_LEFT = "${";

	private final static String KEY_RIGHT = "}";

	private final static String[] OPERATIONS = { "<>", "<=", ">=", "<<", ">>",
			"!=", "=", "<", ">" };
	
	/**
	 * 获取where条件
	 * @param expList
	 * @param parameterContext
	 * @return
	 * @throws SaturnComponentException
	 */
	public static String getCondition(List<String> expList,IParameterContext parameterContext) throws SaturnComponentException{
		
		StringBuffer firstConditionBuffer = new StringBuffer();
		StringBuffer lastConditionBuffer = new StringBuffer();
		List<FieldAndValueVO> list = new ArrayList<FieldAndValueVO>();

		String[] conditions;
		for (String exp : expList) {

			if (null == exp || "".equals(exp.trim())) {
				continue;
			}
			conditions = parseCondition(exp, parameterContext, list);
			firstConditionBuffer.append(getUseableCondition(conditions[0]));
			lastConditionBuffer.append(getUseableCondition(conditions[1]));
		}
		firstConditionBuffer.append(NEWLINE).append(SEPARATE);
		String uniqueKey = saveListInLogicContext(parameterContext, list);
		lastConditionBuffer.append(NEWLINE).append(SEPARATE).append(uniqueKey)
				.append(NEWLINE);

		return firstConditionBuffer.append(lastConditionBuffer).toString();
	}
	
	/**
	 * 根据前提条件获取where条件
	 * @param expList
	 * @param parameterContext
	 * @return
	 * @throws Exception 
	 */
	public static String getConditionWithPremiss(List<String> expList,IParameterContext parameterContext) throws Exception{
		
		List<String> conditions = getParameterStr(expList,parameterContext);
		
		String condition = getCondition(conditions,parameterContext);

		return condition;
	}
	
	/**
	 * 根据前提条件，添加where条件
	 * @param expList
	 * @return
	 * @throws Exception 
	 */
	private static List<String> getParameterStr(List<String> expList,IParameterContext parameterContext) throws Exception {
		
		List<String> conditions = new ArrayList<String>();
		
        for(int i = 0 ;i<expList.size();i++){
        	
        	String flag = expList.get(i++);
        	
        	if("true".equals(flag)){      		
        		String expression = expList.get(i);        		
        		conditions.add(expression);
        	}else{
        		String expr = parseCondition(flag,parameterContext);
        		Object result = ExpressionFactory.createExpression(expr).evaluate(JexlHelper.createContext());
        		if (result instanceof Boolean) {
					Boolean newresult = (Boolean) result;
					if(newresult == true){
						String expression = expList.get(i);        		
		        		conditions.add(expression);
					}
				}
        	}
        }
		return conditions;
	}
	
	private static String getUseableCondition(String condition) {
		if (null == condition || "".equals(condition.trim())) {
			return "";
		}
		return " AND " + condition;
	}

	private static String saveListInLogicContext(IParameterContext parameterContext,
			List<FieldAndValueVO> list) {
		String uniqueKey = getUniqueKey();
		parameterContext.getLogicContext().setValue(uniqueKey, list);
		return uniqueKey;
	}

	/**
	 * 得到唯一的字符串
	 * 
	 * @author zjh
	 * 
	 */
	private static String getUniqueKey() {
		return "" + System.currentTimeMillis() + getRandomNum();
	}

	private static int getRandomNum() {
		return new Random().nextInt(10000);
	}

	/**
	 * 解析条件,解析步骤 
	 * 1:value值替换动态变量 完成表达式首部, ok 
	 * 2:用?替换动态变量 ok
	 * 3:如果?被''包围,则替换掉单引号,完成表达式中部.ok 
	 * 4:取出单独的条件 id = ? ok 
	 * 5:得到 field id ok 
	 * 6:存入vo后存入list ok
	 * 
	 * @param 符合动态输入条件返回解析后的条件数组,如果是普通条件,返回数组中储存的是相同的条件
	 * @author zjh
	 * @throws SaturnComponentException
	 * 
	 */
	private static String[] parseCondition(String condition,
			IParameterContext parameterContext, List<FieldAndValueVO> list)
			throws SaturnComponentException {
		String[] results = new String[2];
		String resultFirst = condition;
		String resultSecond = condition;

		// 每次开始搜索${的起始点 目的是为了防止value中存在${
		int fromIndex = 0;
		while (resultFirst.indexOf(KEY_LEFT, fromIndex) > -1) {
			int indexOfValueLeft = resultFirst.indexOf(KEY_LEFT, fromIndex);
			int indexOfValueRight = resultFirst.indexOf(KEY_RIGHT,
					fromIndex + 1);

			String key = resultFirst.substring(indexOfValueLeft + 2,
					indexOfValueRight);
			String value = (String) parameterContext.getLogicContextValue(KEY_LEFT + key + KEY_RIGHT);

			if (null == value || "".equals(value.trim())) {
				removeCondition(results, key);
				resultFirst = results[0];
				resultSecond = results[1];
				continue;
			}
			resultFirst = resultFirst
					.replace(KEY_LEFT + key + KEY_RIGHT, value);

			String field = getField(resultFirst.substring(fromIndex,
					indexOfValueLeft));
			resultSecond = parseLastCondition(resultSecond, key, field, value,
					list);

			fromIndex = indexOfValueLeft + value.length();

		}
		results[0] = resultFirst;
		results[1] = resultSecond;
		return results;
	}

	protected static void removeCondition(String[] results, String key) {
		results[0] = "";
		results[1] = "";
	}

	/**
	 * 获得完整的字段值 ' or t_char='z' and t_int<>'
	 * 
	 * @author zjh and t_name like '%
	 */
	private static String getField(String condition) {
		condition = condition.replace("like", LIKE);
		int endIndex = -1;

		if (condition.contains(LIKE)) {
			endIndex = condition.lastIndexOf(LIKE);
			condition = condition.substring(0, endIndex).trim();
			endIndex = condition.length();

		} else {
			condition = condition.replace("'", "").trim();
			int length = condition.length();
			String temp = condition.substring(length - 2);
			endIndex = length - 1;

			for (String sign : OPERATIONS) { 
				if (sign.equals(temp)) {
					endIndex = length - 2;
					break;
				}
			}
		}
		condition=condition.substring(0, endIndex).trim();
		endIndex=condition.length();
		int startIndex = condition.lastIndexOf(" ", endIndex) + 1;
		return condition.substring(startIndex, endIndex);
	}

	/**
	 * 解析最后一个条件,将值域用替换,如果?2边有单引号则去掉
	 * 
	 * @author zjh
	 * @param value
	 * @param field
	 * @param list
	 * @throws SaturnComponentException
	 * 
	 */
	private static String parseLastCondition(String lastCondition, String key,
			String field, String value, List<FieldAndValueVO> list)
			throws SaturnComponentException {
		StringBuffer tempBuffer = new StringBuffer();
		String condition = lastCondition.replace("like", LIKE);
		int questionSignIndex = condition.indexOf(KEY_LEFT);
		int beginIndex = condition.lastIndexOf("'", questionSignIndex);
		int likeSignIndex = condition.lastIndexOf(LIKE, questionSignIndex);

		if (hasLike(likeSignIndex, beginIndex, condition)) {
			int endIndex = condition.indexOf("'", questionSignIndex);
			if (-1 == endIndex) {
				throw new SaturnComponentException("The Expression is error.=="
						+ condition);
			}
			String likeKey = condition.substring(beginIndex + 1, endIndex);
			value = likeKey.replace(KEY_LEFT + key + KEY_RIGHT, value);
			tempBuffer.replace(0, tempBuffer.length(), condition.replace("'"
					+ likeKey + "'", "?"));

		} else {
			tempBuffer.replace(0, tempBuffer.length(), condition.replace(
					KEY_LEFT + key + KEY_RIGHT, "?"));
		}

		list.add(setFieldAndValueVO(value, field));

		return removeSingleQuotes(tempBuffer, questionSignIndex);
	}

	private static String removeSingleQuotes(StringBuffer tempBuffer,
			int questionSignIndex) {
		int delRightIndex = tempBuffer.indexOf("'", questionSignIndex);
		int delLeftIndex = tempBuffer.lastIndexOf("'", questionSignIndex);

		if (isDelSingleQuotes(tempBuffer, delLeftIndex, delRightIndex)) {
			tempBuffer.deleteCharAt(delRightIndex);
			tempBuffer.deleteCharAt(delLeftIndex);
		}
		return tempBuffer.toString();
	}

	private static boolean isDelSingleQuotes(StringBuffer tempBuffer, int beginIndex,
			int endIndex) {
		if (isWrongIndex(beginIndex, endIndex)) {
			return false;
		}
		if (!"?".equals(tempBuffer.substring(beginIndex + 1, endIndex).trim())) {
			return false;
		}
		return true;
	}

	private static boolean hasLike(int beginIndex, int endIndex, String condition) {
		if (isWrongIndex(beginIndex, endIndex)) {
			return false;
		}
		if (!LIKE.equals(condition.substring(beginIndex, endIndex).trim())) {
			return false;
		}
		return true;
	}

	private static boolean isWrongIndex(int beginIndex, int endIndex) {
		if (-1 == beginIndex || -1 == endIndex) {
			return true;
		}
		if ((beginIndex >= endIndex)) {
			return true;
		}
		return false;
	}

	/**
	 * 将fielde和value存入vo中
	 * 
	 * @author zjh
	 */
	private static FieldAndValueVO setFieldAndValueVO(String value, String field) {
		FieldAndValueVO vo = new FieldAndValueVO();

		vo.setField(field);
		vo.setValue(value);
		return vo;
	}
	
	private static String parseCondition(String condition,
			IParameterContext parameterContext) {
		String result = condition;
		int fromIndex = 0;
		while (result.indexOf("${", fromIndex) > -1) {
			int indexOfValueLeft = result.indexOf("${", fromIndex);
			int indexOfValueRight = result.indexOf("}", indexOfValueLeft);
			if(indexOfValueRight<indexOfValueLeft){
				return "null";
			}
			String key = result.substring(indexOfValueLeft + 2,
					indexOfValueRight);
			String value = (String) parameterContext.getLogicContextValue(key
					.trim());
			if (value != null && !"".equals(value.trim())) {
				result = result.replace("${" + key + "}", value);
				fromIndex = indexOfValueLeft;
			} else {
				result = result.replace("${" + key + "}", "null");
			}
		}
		return result;
	}
}
